package customer

import (
	"encoding/csv"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
	"server/global"
	commReq "server/model/common/request"
	"server/model/common/response"
	CustomerModel "server/model/customer"
	customerReq "server/model/customer/request"
	"server/utils"
)

type CustomerApi struct{}

func (ca *CustomerApi) GetAllCustomer(c *gin.Context) {
	if list, total, err := customerService.GetAllCustomer(); err != nil {
		response.FailWithMessage("获取失败", c)
		global.TD27_LOG.Error("获取客户列表失败", zap.Error(err))
	} else {
		response.OkWithDetailed(response.PageResult{
			Total: total,
			List:  list,
		}, "获取成功", c)
	}
}

// GetCustomer 获取客户名称
func (ca *CustomerApi) GetCustomer(c *gin.Context) {
	var CustomerSp customerReq.CustomerSearchParams
	CustomerSp.Page, _ = utils.StringToInt(c.Query("currentPage"))
	CustomerSp.PageSize, _ = utils.StringToInt(c.Query("size"))
	CustomerSp.Name = c.Query("name")
	CustomerSp.BusinessName = c.Query("businessName")
	CustomerSp.ServiceStatus, _ = utils.StringToUint(c.Query("serviceStatus"))
	CustomerSp.MaintenanceType, _ = utils.StringToInt8(c.Query("maintenanceType"))
	CustomerSp.Type, _ = utils.StringToUint(c.Query("type"))
	CustomerSp.VipLevel, _ = utils.StringToInt8(c.Query("vipLevel"))

	if list, total, err := customerService.GetCustomer(CustomerSp); err != nil {
		response.FailWithMessage("获取失败", c)
		global.TD27_LOG.Error("获取客户列表失败", zap.Error(err))
	} else {
		response.OkWithDetailed(response.PageResult{
			Page:     CustomerSp.Page,
			PageSize: CustomerSp.PageSize,
			Total:    total,
			List:     list,
		}, "获取成功", c)
	}
}

// AddOrUpdateCustomer 添加/更新客户名称
func (ca *CustomerApi) AddOrUpdateCustomer(c *gin.Context) {
	var customer customerReq.Customer
	_ = c.ShouldBindJSON(&customer)

	// 参数校验
	validate := validator.New()
	if err := validate.Struct(&customer); err != nil {
		response.FailWithMessage("请求参数错误", c)
		global.TD27_LOG.Error("请求参数错误", zap.Error(err))
		return
	}

	if res, action, err := customerService.AddOrUpdateCustomer(customer); err != nil {
		msg := fmt.Sprintf("%s失败, %s", action, err)
		response.FailWithMessage(msg, c)
		global.TD27_LOG.Error("添加失败", zap.Error(err))
	} else {
		msg := fmt.Sprintf("%s成功", action)
		response.OkWithDetailed(res, msg, c)
	}
}

// BatchAddOrUpdateCustomer 批量导入客户信息
func (ca *CustomerApi) BatchAddOrUpdateCustomer(c *gin.Context) {
	fileType := c.Query("type")
	if fileType != "csv" {
		msg := fmt.Sprintf("仅支持csv文件导入，请保证type参数和文件类型均为csv，您的type参数为：%s", fileType)
		response.FailWithMessage(msg, c)
		global.TD27_LOG.Error(msg)
		return
	}

	file, err := c.FormFile("file")
	if err != nil {
		msg := fmt.Sprintf("从表单中获取文件失败，error: %s", err)
		global.TD27_LOG.Error(msg)
		response.FailWithMessage(msg, c)
		return
	}

	// 读取文件内容
	f, err := file.Open()
	if err != nil {
		msg := fmt.Sprintf("读取文件内容失败，error: %s", err)
		global.TD27_LOG.Error(msg)
		response.FailWithMessage(msg, c)
		return
	}

	reader := csv.NewReader(f)
	headerSkipped := false // 声明一个变量来标记是否跳过表头

	// 开启事务
	tx := global.TD27_DB.Begin()

	// 确保在出现错误或painc的情况下回滚事务
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 循环读取并解析每一行数据并添加到数据库
	for {
		record, err := reader.Read()
		if err != nil {
			// 到达文件末尾时，会返回 io.EOF 错误
			if err.Error() == "EOF" {
				break
			}
			msg := fmt.Sprintf("读取文件失败: %s", zap.Error(err))
			global.TD27_LOG.Error(msg)
			response.FailWithMessage(msg, c)
			tx.Rollback()
			global.TD27_LOG.Error("事件回滚了")
			return
		}

		// 如果还没跳过表头，则继续下一次循环，跳过表头
		if !headerSkipped {
			headerSkipped = true
			continue
		}

		customer := CustomerModel.CustomerModel{}
		customer.Name = record[0]
		customer.Type, _ = utils.StringToUint(record[1])
		customer.VipLevel, _ = utils.StringToInt8(record[2])
		customer.ServiceStatus, _ = utils.StringToUint(record[3])
		customer.MaintenanceType, _ = utils.StringToInt8(record[4])
		//customer.BusinessName = record[5]
		customer.ServiceStartDate = utils.ParseDate(record[6])
		customer.ServiceEndDate = utils.ParseDate(record[7])
		customer.Description = record[8]

		// 执行添加操作
		if err := tx.Create(&customer).Error; err != nil {
			msg := fmt.Sprintf("客户%s数据异常,请整理后重新提交,error: %s", customer.Name, err)
			response.FailWithMessage(msg, c)
			global.TD27_LOG.Error(msg)
			// 回滚事务
			tx.Rollback()
			return
		}
	}

	// 提交事务
	tx.Commit()
	response.OkWithMessage("导入成功！", c)
}

// DeleteCustomer 删除客户名称
func (ca *CustomerApi) DeleteCustomer(c *gin.Context) {
	id, _ := utils.StringToInt(c.Param("customerId"))
	var cId commReq.CId
	_ = c.ShouldBindJSON(&cId)

	if err := customerService.DeleteCustomer(id); err != nil {
		response.FailWithMessage("删除失败", c)
		global.TD27_LOG.Error("删除失败", zap.Error(err))
	} else {
		response.OkWithMessage("删除成功", c)
	}
}
